package com.hitqz.robot.biz.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.util.concurrent.RateLimiter;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.*;
import com.hitqz.robot.api.business.entity.PatrolResultEntity;
import com.hitqz.robot.api.business.entity.RobotEntity;
import com.hitqz.robot.api.dispatch.protocol.ProtocolEnum;
import com.hitqz.robot.biz.service.PatrolResultService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.common.core.util.RedisUtils;
import com.hitqz.robot.common.security.service.RobotUser;
import com.hitqz.robot.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@AllArgsConstructor
@RequestMapping("/patrolItemStandard")
@Tag(name = "巡检项标准管理")
@Slf4j
public class PatrolItemStandardController {

    private final RobotService robotService;

    private final PatrolResultService patrolResultService;

    public record CheckTypeVo(String robotSn, List<PatrolCheckTypeDto> checkTypes){}

    public record ItemStandardVo(String robotSn,Long itemId,String name,String url,String valueMax,String valueMin){}

    private final ConcurrentHashMap<String, RateLimiter> limiterMap = new ConcurrentHashMap<>();

    @GetMapping("/checkTypeList")
    @Operation(summary = "获取类型列表")
    public R<List<CheckTypeVo>> checkType(){
        List<CheckTypeVo> list = new ArrayList<>();
        RobotUser user = SecurityUtils.getUser();
        List<String> robotSns = robotService.list().stream().map(RobotEntity::getRobotSn).toList();
        if (robotSns != null && !robotSns.isEmpty()){
            for (String robotSn : robotSns) {
                String jsonStr = RedisUtils.get("patrol:checkTypes:" + robotSn);
                if (StrUtil.isNotBlank(jsonStr)){
                    List<PatrolCheckTypeDto> checkTypes = JSONObject.parseArray(jsonStr, PatrolCheckTypeDto.class);
                    checkTypes = checkTypes.stream()
                            .filter(type-> type.getIsVision()==1
                                    && (Objects.equals(type.getResultType(),"1")||Objects.equals(type.getResultType(),"5"))).toList();
                    list.add(new CheckTypeVo(robotSn,checkTypes));
                }
            }
        }
        return R.ok(list);
    }


    @GetMapping("/strandValue")
    @Operation(summary = "获取类型下的检测项标准列表")
    public R<List<ItemStandardVo>> strandValue(@RequestParam("clientId") String clientId,
                                               @RequestParam("checkTypeId") Long checkTypeId,
                                               @RequestParam(name = "name",required = false) String name){
        List<ItemStandardVo> itemStandardVos = new ArrayList<>();
        String itemsJsonStr = RedisUtils.get("patrol:items:" + clientId);
        String objectsJsonStr = RedisUtils.get("patrol:objects:" + clientId);
        if (StrUtil.isNotBlank(objectsJsonStr) && StrUtil.isNotBlank(itemsJsonStr)) {
            List<PatrolObjectDto> objects = JSONObject.parseArray(objectsJsonStr, PatrolObjectDto.class);
            List<Long> objectIds = objects.stream().filter(o -> Objects.equals(o.getPatrolCheckTypeId(), checkTypeId)).map(PatrolObjectDto::getId).toList();
            List<PatrolItemDto> items = JSONObject.parseArray(itemsJsonStr, PatrolItemDto.class);
            List<PatrolItemDto> list = items.stream().filter(item -> objectIds.contains(Long.valueOf(item.getPatrolObjectId()))).toList();
            if (StrUtil.isNotBlank(name)){
                //筛选
                list = items.stream().filter(item -> item.getName().contains(name)).toList();
            }
            itemStandardVos = list.stream().map(item -> {
                String standardValueStr = RedisUtils.get("patrol:standardValue:" + clientId +":"+ item.getId());
                String valueMax = "";
                String valueMin = "";
                if (StrUtil.isNotBlank(standardValueStr)){
                    String[] split = standardValueStr.split(",");
                    valueMin = split[0];
                    valueMax = split[Math.min(split.length-1,1)];
                }else if (StrUtil.isNotBlank(item.getStandardValue())){
                    String[] split = item.getStandardValue().split(",");
                    valueMin = split[0];
                    valueMax = split[Math.min(split.length-1,1)];
                }
                //只从缓存读取，避免查询时间太长
                String visionMediaUrl = RedisUtils.get("patrol:visionMediaUrl:" + clientId +":"+ item.getId());
                //
//                if (StrUtil.isBlank(visionMediaUrl)){
//                    PatrolResultEntity one = patrolResultService.getOne(Wrappers.<PatrolResultEntity>lambdaQuery().eq(PatrolResultEntity::getItemId, item.getId()).eq(PatrolResultEntity::getItemName, item.getName()).last("limit 1"));
//                    if (one != null){
//                        visionMediaUrl = one.getVisionMediaUrl();
//                        RedisUtils.set("patrol:visionMediaUrl:" + clientId +":"+ item.getId(),visionMediaUrl);
//                    }
//                }
                return new ItemStandardVo(clientId,item.getId(),item.getName(),visionMediaUrl,valueMax,valueMin);
            }).toList();
        }
        return R.ok(itemStandardVos);
    }

    @PutMapping("/strandValue")
    @Operation(summary = "更新检测项标准")
    public R updateStrandValue(@RequestBody ItemStandardVo itemStandardVo){
        if (StrUtil.isBlank(itemStandardVo.valueMax) && StrUtil.isBlank(itemStandardVo.valueMin)){
            //清除
            RedisUtils.del("patrol:standardValue:" + itemStandardVo.robotSn +":"+ itemStandardVo.itemId);
            return R.ok("清除成功");
        }
        String standardValueStr = RedisUtils.get("patrol:standardValue:" + itemStandardVo.robotSn  +":"+ itemStandardVo.itemId);
        RedisUtils.set("patrol:standardValue:" + itemStandardVo.robotSn +":"+ itemStandardVo.itemId,itemStandardVo.valueMin+","+itemStandardVo.valueMax);
        if (!Objects.equals(standardValueStr,itemStandardVo.valueMin+","+itemStandardVo.valueMax)) {
            //历史记录 最多5条
            RobotUser user = SecurityUtils.getUser();
            String key = "patrol:standardValueHistory:" + itemStandardVo.robotSn + ":" + itemStandardVo.itemId;
            String content = DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss") + " "
                    + user.getUsername() + " 修改:" + standardValueStr + " -> "
                    + itemStandardVo.valueMin + "," + itemStandardVo.valueMax;
            // 插入一条修改记录
            RedisUtils.lSet(key, content);
            // 保留最新5条历史记录（避免无限增长）
            RedisUtils.lTrim(key, 0, 4);
        }
        return R.ok();
    }

    @GetMapping("/strandValueHistory")
    @Operation(summary = "获取更改历史")
    public R<List<String>> strandValueHistory(@RequestParam("clientId") String clientId,
                                              @RequestParam("itemId") Long itemId){
        String key = "patrol:standardValueHistory:" + clientId + ":" + itemId;
        List<String> list = RedisUtils.lGet(key, 0, -1);
        return R.ok(list);
    }

    @GetMapping("/visionHistory")
    @Operation(summary = "获取最近几张视觉图片")
    public R<List<String>> pictureHistory(@RequestParam("name") String name,
                                         @RequestParam("itemId") Long itemId){
        List<String> visionHistory = new ArrayList<>();
        List<PatrolResultEntity> list = patrolResultService.list(Wrappers.<PatrolResultEntity>lambdaQuery().isNotNull(PatrolResultEntity::getVisionMediaUrl).eq(PatrolResultEntity::getItemName, name).eq(PatrolResultEntity::getItemId,itemId).orderByDesc(PatrolResultEntity::getId).last("limit 5"));
        if (!list.isEmpty()){
            visionHistory = list.stream().map(PatrolResultEntity::getVisionMediaUrl).toList();
        }
        return R.ok(visionHistory);
    }

    @Operation(summary = "同步到机器人")
    @GetMapping("/sync")
    public R sync(@RequestParam("clientId") String clientId){
        Cache<String, RobotClientSummaryDto> robotCache = SpringUtil.getBean("robotCache");
        if (robotCache.getIfPresent(clientId) == null){
            return R.failed("机器人不在线");
        }
        RateLimiter rateLimiter = limiterMap.computeIfAbsent(clientId, k -> RateLimiter.create(1));
        List<PatrolItemStandardDto> list = new ArrayList<>();
        if (rateLimiter.tryAcquire(10)){
            //获取patrol:standardValue数据
            String itemsJsonStr = RedisUtils.get("patrol:items:" + clientId);
            if (StrUtil.isNotBlank(itemsJsonStr)){
                List<PatrolItemDto> items = JSONObject.parseArray(itemsJsonStr, PatrolItemDto.class);
                for (PatrolItemDto item : items) { 
                    String standardValueStr = RedisUtils.get("patrol:standardValue:" + clientId +":"+ item.getId());
                    PatrolItemStandardDto dto = new PatrolItemStandardDto();
                    dto.setItemId(item.getId());
                    dto.setStandardValue(standardValueStr == null ? "" : standardValueStr);
                    dto.setClientId(clientId);
                    list.add(dto);
                }
            }
            if (!list.isEmpty()){
                // 同步到机器人上
                PatrolItemStandardSyncDto syncDto = new PatrolItemStandardSyncDto();
                syncDto.setStandardList(list);
                RobotSendClientMsgDto msgDto= new RobotSendClientMsgDto();
                msgDto.setCmd(ProtocolEnum.PATROL_STANDARD.getCmd());
                msgDto.setClientId(clientId);
                msgDto.setData(syncDto);
                SpringUtil.getApplicationContext().publishEvent(msgDto);
                log.info("同步数据到机器人:{},size:{}" , clientId , list.size());
            }
        }else {
            return R.failed("操作繁忙,请稍后再试");
        }
        return R.ok();
    }


}
